You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Completes the reopened scope of #25 by making trainer tenure an explicit, editable profile value instead of deriving it permanently from account creation time.
add a month/year Trainer since field to Account Settings
persist the value independently from the instructor account audit timestamp
return it from account creation, login, account refresh, and account update endpoints
keep the browser session synchronized after edits and refreshes
render the chosen value consistently on Trainer History
centralize validation and local-safe month formatting in a shared helper
Why
Trainer History previously used instructors.created_at as a cosmetic proxy for tenure. That value answers when the application account was created, not when the instructor began training, so experienced trainers who joined the app later could not correct the displayed date.
The new trainer_since value uses month precision (YYYY-MM), matching the product requirement while preserving created_at unchanged for audit and debugging purposes.
Data migration
The schema adds an instructor_profiles table keyed by instructor ID.
existing instructors are backfilled from the month portion of created_at
new instructors receive an explicit trainer-since month during account creation
INSERT OR IGNORE ... SELECT keeps the deployment schema idempotent
account reads retain a created_at fallback for defensive compatibility
updates use an upsert so profiles remain repairable if a legacy row is absent
A separate profile table avoids a non-idempotent ALTER TABLE in the schema file, which is intentionally rerun during every Worker deployment.
Client compatibility
Persisted browser sessions from before this field existed are normalized on load. If they contain the existing createdAt value, its month is used temporarily; the normal account refresh then replaces it with the server-authoritative profile value.
Date formatting constructs a local-noon calendar date from the year and month, avoiding UTC boundary shifts.
User impact
Instructors can now open Account Settings, choose the correct start month and year, and save it without changing their login name, profile photo, or account creation timestamp. Trainer History immediately reflects the corrected tenure.
Validation
npm test — 24 tests passed
npm run build — production TypeScript/Vite build passed
npm run lint — passed with three pre-existing warnings
npm --prefix worker run typecheck — passed
git diff --check — passed
schema creation, existing-instructor backfill, and repeated execution verified against an isolated in-memory SQLite database
The local Wrangler D1 runner could not execute on this Windows ARM64 host because its bundled workerd binary does not support that platform; the SQL itself was validated directly with SQLite instead.
The implementation is otherwise coherent, but Trainer since currently accepts future months.
The shared validator checks only YYYY-MM shape and a valid month number. The Worker uses that validator, the database constraint likewise permits any four-digit year, and the has no max value. An instructor can therefore save something like 2035-06, and Trainer History will display “Trainer since June 2035.”
That is invalid for a tenure start field and should be rejected at both boundaries:
Add max={currentLocalMonth} to the month input.
Have the Worker reject trainerSince values later than the current month.
Add tests covering the current month as valid and the next month as invalid.
The rest looks strong:
tenure is correctly separated from account creation timestamps;
legacy instructors are idempotently backfilled;
missing profile rows retain a defensive created_at fallback;
profile updates use an upsert;
old browser sessions are normalized and later refreshed from the server;
month display avoids UTC date shifting.
CI is fully green across tests, lint, build, dependency installation, and Worker type-checking.
Addressed the requested future-month guard in 79f6620.
The shared trainer-since validator now accepts valid YYYY-MM values only through the current month, so the Worker rejects future tenure dates server-side.
The Account Settings month input now uses the current local month as its max.
Tests explicitly cover the current month as valid, the following month as invalid, and local-month derivation near a day boundary.
Validation after the change:
npm test — 25/25 passed
npm run build — passed
npm run lint — passed with the same three pre-existing warnings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the reopened scope of #25 by making trainer tenure an explicit, editable profile value instead of deriving it permanently from account creation time.
Why
Trainer History previously used
instructors.created_atas a cosmetic proxy for tenure. That value answers when the application account was created, not when the instructor began training, so experienced trainers who joined the app later could not correct the displayed date.The new
trainer_sincevalue uses month precision (YYYY-MM), matching the product requirement while preservingcreated_atunchanged for audit and debugging purposes.Data migration
The schema adds an
instructor_profilestable keyed by instructor ID.created_atINSERT OR IGNORE ... SELECTkeeps the deployment schema idempotentcreated_atfallback for defensive compatibilityA separate profile table avoids a non-idempotent
ALTER TABLEin the schema file, which is intentionally rerun during every Worker deployment.Client compatibility
Persisted browser sessions from before this field existed are normalized on load. If they contain the existing
createdAtvalue, its month is used temporarily; the normal account refresh then replaces it with the server-authoritative profile value.Date formatting constructs a local-noon calendar date from the year and month, avoiding UTC boundary shifts.
User impact
Instructors can now open Account Settings, choose the correct start month and year, and save it without changing their login name, profile photo, or account creation timestamp. Trainer History immediately reflects the corrected tenure.
Validation
npm test— 24 tests passednpm run build— production TypeScript/Vite build passednpm run lint— passed with three pre-existing warningsnpm --prefix worker run typecheck— passedgit diff --check— passedThe local Wrangler D1 runner could not execute on this Windows ARM64 host because its bundled
workerdbinary does not support that platform; the SQL itself was validated directly with SQLite instead.Closes #25